using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Nirvana
{
    /// <summary>
    /// 分块
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class SquareBlock<T> where T : class
    {
        private T[][] _blocks;
        private Vector3 _offset;
        private int _blockRange;
        private int _blockCount;

        /// <summary>
        /// 初始化正方形块数据
        /// </summary>
        /// <param name="blocks">块数组</param>
        /// <param name="offset">块形成的正方形的左下角位置</param>
        /// <param name="blockRange">每个块的大小</param>
        /// <param name="blockCount">块的数量</param>
        public void Init(T[][] blocks, Vector3 offset, int blockRange, int blockCount)
        {
            _blocks = blocks;
            _offset = offset;
            _blockRange = blockRange;
            _blockCount = blockCount;
        }

        public virtual void UnInit()
        {
            _blocks = null;
        }

        public abstract void Update(ref Vector3 playerPos, float offsetDistance);

        /// <summary>
        /// 是否需要更新，偏移的距离大于块的大小，则需要更新
        /// </summary>
        /// <param name="offsetDistance"></param>
        /// <returns></returns>
        protected virtual bool IsNeedUpdate(float offsetDistance)
        {
            return offsetDistance >= _blockRange;
        }

        /// <summary>
        /// 寻找块数据并返回
        /// </summary>
        /// <param name="x"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        protected T FindBlock(int x, int z)
        {
            if (_blocks != null)
            {
                if (z >= 0 && z < _blocks.Length)
                {
                    T[] blocks = _blocks[z];
                    if (x >= 0 && x < blocks.Length)
                    {
                        return blocks[x];
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// 计算玩家所在位置为中心所需要显示的所有块的范围
        /// </summary>
        /// <param name="playerPos">玩家位置</param>
        /// <param name="minX"></param>
        /// <param name="minZ"></param>
        /// <param name="maxX"></param>
        /// <param name="maxZ"></param>
        protected void CalcBoundary(ref Vector3 playerPos, out int minX, out int minZ, out int maxX, out int maxZ)
        {
            // 玩家所在的块索引位置
            Vector3 blockPos = (playerPos - _offset) / _blockRange;
            int x = (int) blockPos.x;
            int z = (int) blockPos.z;

            int maxBlockCount = _blockCount / 2;
            minX = x - maxBlockCount;
            minZ = z - maxBlockCount;
            maxX = x + maxBlockCount + 1;
            maxZ = z + maxBlockCount + 1;
        }
    }
}